package com.bq.server.exception;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.bq.server.base.ErrorCode;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Objects;

/**
 * 业务异常
 *
 * @author: ChenSH
 * @date: Create by in 09:45 2019-09-20
 */
public class BusinessException extends RuntimeException implements ErrorCode {
    /**
     * 错误代码
     */
    private Integer errorCode;

    protected BusinessException(Integer errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }


    public BusinessException(Throwable cause) {
        super(cause);
    }


    @Override
    public Integer getCode() {
        return errorCode;
    }

    @Override
    public String getDescribe() {
        return getMessage();
    }

    @Override
    public String name() {
        throw new UnsupportedOperationException();
    }

    public static BusinessException of(ErrorCode errorCode) {
        return of(errorCode.getCode(), errorCode.getDescribe());
    }

    public static BusinessException of(ErrorCode errorCode, Throwable cause) {
        return of(errorCode.getCode(), errorCode.getDescribe(), cause);
    }

    public static BusinessException of(Integer errorCode, String describe) {
        return of(errorCode, describe, null);
    }

    public static BusinessException of(Integer errorCode, String describe, Throwable cause) {
        return new BusinessException(errorCode, describe, cause);
    }


    /**
     * 业务异常{@link BusinessException} 断言工具类
     */
    public static class Assert {


        /**
         * 占位符支持
         *
         * @param arguments 占位符字符串对应的参数
         * @see #isTrue(boolean, String)
         * @see MessageFormat#format(String, Object...)
         */
        public static void isTrue(boolean expression, String pattern, Object... arguments) {
            String message = MessageFormat.format(pattern, arguments);
            isTrue(expression, message);
        }

        /**
         * @see #isTrue(boolean, Integer, String)
         */

        public static void isTrue(boolean expression, String message) {
            isTrue(expression, null, message);
        }

        /**
         * 断言是true，expression = false 抛出 BusinessException 异常
         *
         * @param expression 表达式
         * @param errorCode  错误码
         * @param arguments  格式化参数
         * @see BusinessException
         */
        public static void isTrue(boolean expression, ErrorCode errorCode, Object... arguments) {
            if (!expression) {
                throw errorCode.businessException(arguments);
            }
        }

        /**
         * 断言是true，expression = false 抛出 BusinessException 异常
         *
         * @param expression 表达式
         * @param errorCode  错误编码
         * @param message    错误信息
         * @see BusinessException
         */
        public static void isTrue(boolean expression, Integer errorCode, String message) {
            if (!expression) {
                throwBusinessException(errorCode, message);
            }
        }

        /**
         * 占位符支持
         *
         * @param arguments 占位符字符串对应的参数
         * @see #isFalse(boolean, String)
         * @see MessageFormat#format(String, Object...)
         */
        public static void isFalse(boolean expression, String pattern, Object... arguments) {
            String message = MessageFormat.format(pattern, arguments);
            isFalse(expression, message);
        }

        /**
         * @see #isFalse(boolean, Integer, String)
         */
        public static void isFalse(boolean expression, String message) {
            isFalse(expression, null, message);
        }

        /**
         * 断言是false，expression = true 抛出 BusinessException 异常
         *
         * @param expression 表达式
         * @param errorCode  错误码
         * @param arguments  格式化参数
         * @see BusinessException
         */
        public static void isFalse(boolean expression, ErrorCode errorCode, Object... arguments) {
            if (expression) {
                throw errorCode.businessException(arguments);
            }
        }

        /**
         * 断言是false，expression = true 抛出 BusinessException 异常
         *
         * @param expression 表达式
         * @param errorCode  错误编码
         * @param message    错误信息
         * @see BusinessException
         */
        public static void isFalse(boolean expression, Integer errorCode, String message) {
            if (expression) {
                throwBusinessException(errorCode, message);
            }
        }

        /**
         * 断言不是空
         *
         * @see String#format(String, Object...)
         */
        public static void notNull(Object obj, String format, Object... arguments) {
            String message = String.format(format, arguments);
            notNull(obj, message);
        }

        /**
         * 断言不是空
         */
        public static void notNull(Object obj, String message) {
            if (obj == null) {
                throwBusinessException(null, message);
            }
        }

        /**
         * 断言不是空白
         * <pre>
         * notBlank(null)      = true
         * notBlank("")        = true
         * notBlank(" ")       = true
         * notBlank("bob")     = false
         * notBlank("  bob  ") = false
         * </pre>
         */
        public static void notBlank(CharSequence cs, String message) {
            if (StrUtil.isBlank(cs)) {
                throwBusinessException(null, message);
            }
        }

        public static void notEmpty(Collection<?> collection, String message) {
            if (CollUtil.isEmpty(collection)) {
                throwBusinessException(null, message);
            }
        }

        public static void notEmpty(Collection<?> collection, ErrorCode errorCode, Object... arguments) {
            if (CollUtil.isEmpty(collection)) {
                throw errorCode.businessException(arguments);
            }
        }

        private static void throwBusinessException(Integer errorCode, String message) {
            throw BusinessException.of(errorCode, message);
        }

        /**
         * 断言相等
         */
        public static void eq(Object obj1, Object obj2, ErrorCode errorCode, Object... arguments) {
            isTrue(Objects.equals(obj1, obj2), errorCode, arguments);
        }

        public static void notNull(Object obj, ErrorCode errorCode, Object... arguments) {
            isTrue(Objects.nonNull(obj), errorCode, arguments);
        }
    }


}
